package com.kygeng.springframework.context.annotation;

import cn.hutool.core.util.StrUtil;
import com.kygeng.springframework.beans.factory.config.BeanDefinition;
import com.kygeng.springframework.beans.factory.support.BeanDefinitionRegistry;
import com.kygeng.springframework.stereotype.Component;

import java.util.Set;

/**
 * @Title: ClassPathBeanDefinitionScanner
 * @Author: kygeng
 * @Package: com.kygeng.springframework.context.annotation
 * @Date: 2024/8/12 9:38
 * @Description:是继承自 ClassPathScanningCandidateComponentProvider 的具体扫描包处理的类，在 doScan 中除了获取到扫描的类信息以后，还需要获取 Bean 的作用域和类名
 */
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

    private BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    public void doScan(String... basePackages) {
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition beanDefinition : candidates) {
                //解析Bean的作用域
                String beanScope = resolveBeanScope(beanDefinition);
                if (StrUtil.isNotEmpty(beanScope)) {
                    beanDefinition.setScope(beanScope);
                }
                String beanName = determineBeanName(beanDefinition);
                registry.registerBeanDefinition(beanName, beanDefinition);
            }
        }

        //注册处理注解的 BeanPostProcessor(@Autowired、@Value)
        registry.registerBeanDefinition("com.kygeng.springframework.context.annotation.internalAutowiredAnnotationProcessor",new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
    }

    //获取Bean的名称，如果不配置类名基本都是把首字母缩写。
    private String determineBeanName(BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getBeanClass();
        Component component = beanClass.getAnnotation(Component.class);
        String value = component.value();
        if (StrUtil.isEmpty(value)) {
            value = StrUtil.lowerFirst(beanClass.getSimpleName());
        }
        return value;
    }

    //解析Bean的作用域
    private String resolveBeanScope(BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getBeanClass();
        Scope scope = beanClass.getAnnotation(Scope.class);
        if (null != scope) {
            return scope.value();
        }
        return StrUtil.EMPTY;
    }


}
